#include "thread_t.h"

thread_t::thread_t( uint32_t tid_, pull_task_fun_t &fun_, exit_fun_t exit_fun_ )
	:idle_timeout(UINT32_MAX),
	pull_task(fun_),
	exit_fun(exit_fun_),
	tid(tid_)
{
	b_run = false;
}

thread_t::~thread_t(void)
{

}
int thread_t::get_status()
{
	return status.load();
}

void thread_t::run( task_ptr_t &task_ )
{
	lock_guard_t lock_guard(mutex);
	if (status == suspend)
	{
		task = task_;
		wake_up();
	}
}

void thread_t::start()
{
	b_run = true;
	thread = std::make_shared<std::thread>(&thread_t::loop,this);
}

void thread_t::stop()
{
	b_run = false;

	if (status == suspend){
		wake_up ();
	}
	if(thread->joinable()){
		thread->join();
	}
	
}

void thread_t::set_idle_timeout(uint32_t idle_timeout_ )
{
	idle_timeout = idle_timeout_;
}

void thread_t::wake_up()
{
	status = runing;
	cond_var.notify_one();
}

void thread_t::loop()
{
	while(b_run)
	{
		//mutex.lock();
		if (task.use_count() == 0)
		{
		//	mutex.unlock();

			bool rc = pull_task(task);
			if (rc == false)
			{
				to_sleep();
			}
			else
			{
				to_work();
			}
		}
		else
		{
		//	mutex.unlock();
			to_work();
		}
	}
	exit_fun(tid);
}

void thread_t::to_sleep()
{
	status = suspend;
	unique_lock_t unique_lock(cond_var_mutex);
	if (cond_var.wait_for(unique_lock, std::chrono::microseconds(idle_timeout)) 
		== std::cv_status::timeout)
	{
		wait_timeout();
	}
}

void thread_t::wait_timeout()
{
	b_run = false;
	detach();
}

void thread_t::to_work()
{
	task->do_work();
	task.reset();
}

uint32_t thread_t::get_tid()
{
	return tid;
}

void thread_t::detach()
{
	thread->detach();
}


